support native interpolation easing#57237
Open
zeyap wants to merge 1 commit into
Open
Conversation
Summary:
## Changelog:
[General] [Added] - support native driven AnimatedValue interpolation easing
Interpolation with easing on AnimatedValue was not supported with native driver, example like below simply doesn't work, because easing function is called on JS thread. This is not solved with shared backend.
```
const progress = useAnimatedValue(0);
const easedX = progress.interpolate({
inputRange: [0, 1],
outputRange: [0, DISTANCE],
easing: Easing.inOut(Easing.cubic),
});
Animated.timing(progress, {
toValue: 1,
duration: 1500,
useNativeDriver: true,
}).start();
// JS error: Interpolation property 'easing' is not supported by native animated module
```
## How it works
The JS `easing` function is sampled and baked into the native interpolation config as a compact set of non-uniform `[position, value]` stops — the same representation as CSS `linear()`:
- JS (`AnimatedInterpolation`): densely samples the easing curve, then simplifies it with Ramer–Douglas–Peucker into non-uniform stops. The simplification tolerance is derived from the interpolation's output span so the on-screen error stays ~sub-pixel — flat curves collapse to a few stops, curvy ones keep more (bounded by the dense-sample budget). `easingStops` is emitted only when an `easing` is set (and is not the linear identity).
- Native (`InterpolationAnimatedNode`): applies the stops to each segment's normalized ratio via binary search + linear interpolation. `easing` is now an accepted interpolation param, so the "not supported" error is gone.
Overshoot is preserved: easings that leave `[0, 1]` (e.g. `Easing.back`, `Easing.elastic`) keep their excursion even under `extrapolate: 'clamp'`, matching the JS driver — `clamp`/`identity` only apply to out-of-range input, not to the easing's own excursion. Works for all output types since easing acts on the normalized ratio, not the output values.
## Known limitation
Color/platform_color interpolation under an overshoot easing can push channel values outside `[0, 255]`, which currently wrap on the native `uint8_t` cast (JS instead emits out-of-gamut). Not addressed here.
Differential Revision: D108760799
|
@zeyap has exported this pull request. If you are a Meta employee, you can view the originating Diff in D108760799. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
Changelog:
[General] [Added] - support native driven AnimatedValue interpolation easing
Interpolation with easing on AnimatedValue was not supported with native driver, example like below simply doesn't work, because easing function is called on JS thread. This is not solved with shared backend.
How it works
The JS
easingfunction is sampled and baked into the native interpolation config as a compact set of non-uniform[position, value]stops — the same representation as CSSlinear():AnimatedInterpolation): densely samples the easing curve, then simplifies it with Ramer–Douglas–Peucker into non-uniform stops. The simplification tolerance is derived from the interpolation's output span so the on-screen error stays ~sub-pixel — flat curves collapse to a few stops, curvy ones keep more (bounded by the dense-sample budget).easingStopsis emitted only when aneasingis set (and is not the linear identity).InterpolationAnimatedNode): applies the stops to each segment's normalized ratio via binary search + linear interpolation.easingis now an accepted interpolation param, so the "not supported" error is gone.Overshoot is preserved: easings that leave
[0, 1](e.g.Easing.back,Easing.elastic) keep their excursion even underextrapolate: 'clamp', matching the JS driver —clamp/identityonly apply to out-of-range input, not to the easing's own excursion. Works for all output types since easing acts on the normalized ratio, not the output values.Known limitation
Color/platform_color interpolation under an overshoot easing can push channel values outside
[0, 255], which currently wrap on the nativeuint8_tcast (JS instead emits out-of-gamut). Not addressed here.Differential Revision: D108760799